pub mod life;
pub mod map;
pub mod population;

use clap::{App, Arg};

use crate::map::{Map, MapNode};

use std::fs;
use std::sync::Arc;

pub fn init_matches<'a>() -> clap::ArgMatches<'a> {
    App::new("Tsp")
        .version("0.1.0")
        .about("使用遗传算法求出旅行商问题的近似解")
        .arg(
            Arg::with_name("pn")
                .long("pn")
                .value_name("INT")
                .default_value("30")
                .help("生态群系大小")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("pm")
                .long("pm")
                .value_name("DOUBLE")
                .default_value("0.1")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("pc")
                .long("pc")
                .value_name("DOUBLE")
                .default_value("0.8")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("times")
                .long("times")
                .value_name("INT")
                .help("迭代次数")
                .default_value("100")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("debug")
                .long("debug")
                .value_name("DEBUG LEVEL")
                .help("WARN/INFO/DEBUG/TRACE")
                .default_value("WARN")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("data")
                .help("你想要计算的图")
                .index(1)
                .required(true),
        )
        .get_matches()
}

pub fn init_log(log_level: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = pretty_env_logger::formatted_builder();
    builder.parse_filters(log_level);
    builder.try_init()?;

    Ok(())
}

pub fn read_map(data_file: &str) -> Result<Map, std::io::Error> {
    let mut map: Vec<Arc<MapNode>> = Vec::new();
    let read_buffer = fs::read_to_string(data_file)?;

    for (line, current_line) in read_buffer.lines().enumerate() {
        let current_line: Vec<f64> = current_line
            .split_whitespace()
            .map(|x| x.parse::<f64>().unwrap())
            .collect();

        log::debug!("Add MapNode {:?}", current_line);
        map.push(Arc::new(MapNode::new(
            line as u32,
            current_line[0],
            current_line[1],
        )));
    }

    Ok(Map::new(map))
}
